<?php
class ClassLoader
{
    /**
     * 是否注册
     */
    protected static $_registed = false;

	/**
	 * 别名
	 *
	 * @var array
	 */
    protected static $_aliases = array();

	/**
	 * app支持的类类型. 默认的lib不算在之内
	 *
	 * @var array
	 */
    protected static $_supportAppTypes = ['ctl', 'mdl', 'ego', 'api', 'middleware'];

    /**
	 * 已经加载的类
	 *
	 * @var array
	 */
    protected static $_registers = [];

    /**
	 * app支持的类型和目录的对应关系, 如果$_supportAppTypes里有定义, 而此
	 * 定义中不存在, 那么默认用类型名作为目录名.
	 *
	 * @var array
	 */
    protected static $_supportAppTypesCorrDirectory = ['ctl' => 'controller',
                                                       'mdl' => 'model'];
    /**
     * 进行注册
     */
    public static function register()
    {
        if (!static::$_registed) {
            static::$_registed = spl_autoload_register(['\ClassLoader', 'load']);
        }
    }

    /**
     * 注册别名
     */
    public static function addAliases($aliases)
    {
        static::$_aliases = array_merge(static::$_aliases, $aliases);
    }

    public static function load($className)
    {
        // 是否存在别名
        if (array_key_exists($className, static::$_aliases)) {
            return class_alias(static::$_aliases[$className], $className);
        }

        list($appId) = $fragments = explode('_', $className);

        if (isset($fragments[1]) && in_array($fragments[1], static::$_supportAppTypes)) {
            $type = $fragments[1];
            try {
                static::commonLoad($appId, $className, $type, implode('/', array_slice($fragments, 2)));
            } catch (RuntimeException $e) {

            }
        } elseif (isset($fragments[1]))  {
            static::commonLoad($appId, $className, 'lib', implode('/', array_slice($fragments, 1)));
        }
    }

    public static function commonLoad($appId, $className, $type, $classNamePath)
    {
        $typePath = isset(static::$_supportAppTypesCorrDirectory[$type]) ? static::$_supportAppTypesCorrDirectory[$type] : $type;
        $relativePath = sprintf('/%s/%s/%s.php', $appId, $typePath, $classNamePath);
        $path = APP_DIR . $relativePath;
        if (!isset(static::$_registers[$path])) {
            if(__include_file($path)) {
                static::$_registers[$path] = true;
                return;
            } elseif($type == 'mdl') {
                throw new RuntimeException("没有定义 $className model类");
            }

        } else {
            return;
        }

        throw new RuntimeException('Don\'t find '.$type.' file:'.$className);

    }
}

/**
 * 作用范围隔离
 *
 * @param $file
 * @return mixed
 */
function __include_file($file)
{
    if(is_file($file)) {
        include $file;
        return true;
    }
    return false;
}

function __require_file($file)
{
    if(is_file($file)) {
        require $file;
        return true;
    }
    return false;
}